import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.List;
import java.awt.event.*;
import java.util.*;

public class TestDraw extends JFrame{// JFrame对应窗口,可以理解成一个画框
    // 定义一个面板
    private MyPanel myPanel = null;
    public TestDraw(){// 构造器
        myPanel = new MyPanel();
        // 将面板放入画框
        this.add(myPanel);
        this.addKeyListener(myPanel);
        this.setSize(1300,950);// 设置画框大小  宽 高
        this.setVisible(true);// 可以显示
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 关闭画框就退出程序

        // 启动 MyPanel线程,让他不断刷新
        Thread t = new Thread(myPanel);
        t.start();

        // 增加响应关闭窗口的监听器
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                Recorder.setEnemies(MyPanel.enemies);
                Recorder.setHero(MyPanel.hero);
                Recorder.keepRecord();
                System.exit(0);
            }
        });
    }
    // 添加方法选择上一局或者重新开始
    public static boolean choice(){
        System.out.println("请输入: ");
        System.out.println("1. 继续上一局");
        System.out.println("2. 开始新游戏");
        Scanner scanner = new Scanner(System.in);
        int choice = scanner.nextInt();
        switch (choice){
            case 1:
                return true;
            case 2:
                return false;
        }
        return false;
    }

    public static void main(String[] args) {
        new TestDraw();
        // 检测游戏是否结束
        new Thread(() -> {
            File file = new File(Recorder.getRecordPath());
            while (true){

                if (!MyPanel.hero.isLive){
                    System.out.println("失败!");
                    if (file.exists()){
                        file.delete();
                    }
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException interruptedException) {
                        interruptedException.printStackTrace();
                    }
                    System.exit(0);
                }else if (MyPanel.enemies.size() == 0){
                    System.out.println("胜利!");
                    if (file.exists()){
                        file.delete();
                    }
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException interruptedException) {
                        interruptedException.printStackTrace();
                    }
                    System.exit(0);
                }
            }
        }).start();
    }
}
// 定义一个面板 game.MyPanel,继承JPanel,画图形就在面板上画
// 为了让 MyPanel 不断重绘,让他变成一个线程
class MyPanel extends JPanel implements KeyListener,Runnable{// 监听键盘事件

    static Hero hero = null;// 定义坦克
    static Vector<Enemy> enemies = new Vector<>();// 考虑到多线程下
    Vector<Bomb> bombs = new Vector<>();// 用于存放炸弹
    int x = 200;// 初始坦克横坐标
    int y = 500;// 初始坦克纵坐标
    int enemySize = 6;
    Graphics g = null;
    Recorder recorder = new Recorder();

    // 定义三张炸弹图片
    Image image1 = null;
    Image image2 = null;
    Image image3 = null;

    public MyPanel() {
        this.hero = new Hero(x,y);// 初始化坦克
        hero.setSpeed(2);// 控制玩家速度

        boolean continueLastGame = TestDraw.choice();
        // 初始化敌人的坦克
        // 判断是否存在该文件,不存在则开始新游戏
        File file = new File(Recorder.getRecordPath());
        if (continueLastGame && file.exists()){
            try {
                BufferedReader reader = new BufferedReader(new FileReader("src/recorder.txt"));
                String read = "";
                List<String> list = new ArrayList<>();
                while ((read = reader.readLine()) != null){
                    list.add(read);
                }
                // 击败敌人坦克数
                int count = Integer.parseInt(list.get(0));
                Recorder.setAllEnemyTankNum(count);
                // 拿到数据初始化坦克
                for (int i = 1; i < list.size(); i++) {
                    String str = list.get(i);
                    Node node = new Node(str);
                    Tank tank = node.createTank();
                    if (tank instanceof Enemy){
                        Enemy enemy = (Enemy)tank;
                        new Thread(enemy).start();// 启动该敌人坦克线程
                        enemies.add(enemy);
                    }else {
                        hero = (Hero)tank;
                    }
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else {
            for (int i = 0; i < enemySize; i++) {
                Enemy enemy = new Enemy(100*(i+1),0);
                enemy.setDirect(2);
                new Thread(enemy).start();// 启动该敌人坦克线程
                enemies.add(enemy);
            }
        }
        // 传入 enemies 对象给敌人坦克,比较是否重叠
        for (int i = 0; i < enemies.size(); i++) {
            Enemy enemy = enemies.get(i);
            enemy.setEnemies(enemies);
        }
        // 初始化图片
        image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_1.gif"));
        image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_2.gif"));
        image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_3.gif"));

        // 播放指定的音乐
        AePlayWave playMusic = new AePlayWave("src/111.wav");
        new Thread(playMusic).start();// 开启音乐播放线程
    }

    /**
     * @param g  相当于画笔
     * Graphics 有很多方法
     */
    @Override
    public void paint(Graphics g) {// 绘图方法
        this.g = g;
        super.paint(g);// 调用父类的方法完成初始化
        g.fillRect(0,0,1000,750);// 填充画框
        // 画出右侧计数
        showInfo(g);

        if (hero.isLive){
            // 画自己的坦克
            drawTank(hero.getX(),hero.getY(),g,hero.getDirect(),0);
            // 画自己的子弹
            for (int i = 0; i < hero.shots.size(); i++) {
                Shot shot = hero.shots.get(i);
                if(shot.isLive){
                    g.fill3DRect(shot.x,shot.y,2,2,false);
                }else {
                    // 移除该子弹
                    hero.shots.remove(shot);
                }
            }
        }

        // 画敌人的坦克
        for (int i = 0; i < enemies.size(); i++) {
            // 取出坦克
            Enemy enemy = enemies.get(i);
            drawTank(enemy.getX(),enemy.getY(),g,enemy.getDirect(),1);
            // 画出该坦克的所有子弹
            for (int j = 0; j < enemy.shots.size(); j++) {
                Shot shot = enemy.shots.get(j);
                if(shot.isLive){
                    g.fill3DRect(shot.x,shot.y,2,2,false);
                }else {
                    // 移除该子弹
                    enemy.shots.remove(shot);
                }
            }
        }
        try {
            Thread.sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 画炸弹
        for (int i = 0; i < bombs.size(); i++) {
            Bomb bomb = bombs.get(i);
            // 根据当前对象的 life值,画出
            if (bomb.life > 6){
                g.drawImage(image1,bomb.x,bomb.y,60,60,this);
            }else if(bomb.life > 3){
                g.drawImage(image2,bomb.x,bomb.y,60,60,this);
            }else {
                g.drawImage(image3,bomb.x,bomb.y,60,60,this);
            }
            bomb.cutLife();
            if (bomb.life == 0){
                bombs.remove(bomb);
            }
        }
    }
    // 击中坦克数
    public void showInfo(Graphics g){
        // 画出玩家总成绩
        g.setColor(Color.BLACK);
        Font font = new Font("黑体",Font.BOLD,25);
        g.setFont(font);

        g.drawString("累计击毁敌方坦克: ",1020,30);
        drawTank(1020,60,g,0,1);// 画出一个向上的敌方坦克

        g.setColor(Color.BLACK);
        g.drawString(recorder.getAllEnemyTankNum() + "",1080,100);
    }
    // 判断我方的子弹是否击中敌人 / 我
    public void hitTank(Shot shot,Tank tank){
        switch (tank.getDirect()){
            case 0:
            case 2:
                if (shot.x > tank.getX() && shot.x < tank.getX()+40
                        && shot.y > tank.getY() && shot.y < tank.getY()+60){
                    if (tank instanceof Enemy) {
                        enemies.remove(tank);
                        shot.isLive = false;
                        Bomb bomb = new Bomb(tank.getX(),tank.getY());
                        bombs.add(bomb);
                        recorder.addEnemyTankNum();
                    }else if (tank instanceof Hero && hero.isLive){
                        hero.isLive = false;
                        Bomb bomb = new Bomb(tank.getX(),tank.getY());
                        bombs.add(bomb);
                    }
                }
                break;
            case 1:
            case 3:
                if (shot.x > tank.getX() && shot.x < tank.getX()+60
                        && shot.y > tank.getY() && shot.y < tank.getY()+40){

                    if (tank instanceof Enemy){
                        enemies.remove(tank);
                        shot.isLive = false;
                        Bomb bomb = new Bomb(tank.getX(),tank.getY());
                        bombs.add(bomb);
                        recorder.addEnemyTankNum();
                    }else if (tank instanceof Hero && hero.isLive){
                        hero.isLive = false;
                        shot.isLive = false;
                        Bomb bomb = new Bomb(tank.getX(),tank.getY());
                        bombs.add(bomb);
                    }
                }
                break;
        }
    }
    // 画坦克 --- 方法
    //                  横坐标   纵坐标   画笔         坦克的方向   坦克类型
    public void drawTank(int x, int y, Graphics g, int direct, int type){

        switch (type){
            case 0:
                // 我方坦克
                g.setColor(Color.cyan);
                break;
            case 1:
                // 敌方坦克
                g.setColor(Color.yellow);
        }

        // 根据方向,画坦克,画子弹
        switch (direct){
            case 0:
                // 向上
                g.fill3DRect(x,y,10,60,false);// 左轮子
                g.fill3DRect(x+30,y,10,60,false);// 右轮子
                g.fill3DRect(x+10,y+10,20,40,false);// 中间矩形
                g.fillOval(x+10,y+20,20,20);// 中间圆形
                g.drawLine(x+20,y,x+20,y+30);
                break;
            case 1:
                // 向右
                g.fill3DRect(x,y,60,10,false);// 左轮子
                g.fill3DRect(x,y+30,60,10,false);// 右轮子
                g.fill3DRect(x+10,y+10,40,20,false);// 中间矩形
                g.fillOval(x+20,y+10,20,20);// 中间圆形
                g.drawLine(x+60,y+20,x+30,y+20);
                break;
            case 2:
                // 向下
                g.fill3DRect(x,y,10,60,false);// 左轮子
                g.fill3DRect(x+30,y,10,60,false);// 右轮子
                g.fill3DRect(x+10,y+10,20,40,false);// 中间矩形
                g.fillOval(x+10,y+20,20,20);// 中间圆形
                g.drawLine(x+20,y+60,x+20,y+30);
                break;
            case 3:
                // 向左
                g.fill3DRect(x,y,60,10,false);// 左轮子
                g.fill3DRect(x,y+30,60,10,false);// 右轮子
                g.fill3DRect(x+10,y+10,40,20,false);// 中间矩形
                g.fillOval(x+20,y+10,20,20);// 中间圆形
                g.drawLine(x,y+20,x+30,y+20);
                break;
        }
    }

    // 有字符输出
    @Override
    public void keyTyped(KeyEvent e) {
    }
    // 当某个键按下
    long begin = 0;
    @Override
    public void keyPressed(KeyEvent e) {
        // 根究用户输入的键,来控制坦克移动
        if (e.getKeyCode() == KeyEvent.VK_DOWN){
            // 向下的键盘对应的 code值
            hero.setDirect(2);
            hero.down();
        }else if (e.getKeyCode() == KeyEvent.VK_UP){
            hero.setDirect(0);
            hero.up();
        }else if (e.getKeyCode() == KeyEvent.VK_LEFT){
            hero.setDirect(3);
            hero.left();
        }else if (e.getKeyCode() == KeyEvent.VK_RIGHT){
            hero.setDirect(1);
            hero.right();
        }else if (e.getKeyCode() == KeyEvent.VK_SPACE){
            if (begin == 0 || System.currentTimeMillis() - begin > 500){
                if (hero.isLive){
                    hero.shotEnemy();
                }
                begin = System.currentTimeMillis();
            }
        }
        // 让面板重绘
        this.repaint();
    }
    // 当某个键松开
    @Override
    public void keyReleased(KeyEvent e) {
    }
    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(50);
                this.repaint();
                // 判断是否有敌人坦克被击中
                for (int i = 0; i < hero.shots.size(); i++) {
                    Shot shot = hero.shots.get(i);
                    if (shot.isLive){
                        // 如果子弹还活着
                        for (int j = 0; j < enemies.size(); j++) {
                            Enemy enemy = enemies.get(j);
                            hitTank(shot,enemy);
                        }
                    }
                }
                // 判断自己是否被击中
                for (int i = 0; i < enemies.size(); i++) {
                    Enemy enemy = enemies.get(i);
                    for (int j = 0; j < enemy.shots.size(); j++) {
                        Shot shot = enemy.shots.get(j);
                        if (shot.isLive) {
                            hitTank(shot, hero);
                        }
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}